package systems.languages;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.InvalidPropertiesFormatException;
import java.util.LinkedList;
import java.util.Properties;

import systems.configurations.SystemConfiguration;

/**
 * MultiLanguages class allows the game to use different languages files store in a specific folder.
 * It's based on the singleton design pattern.
 * @author Baptiste Legrand & Benjamin Orman
 * @version 3.0
 */
public class MultiLanguages {
	private static Properties multiLanguagesProperties = new Properties();
	private static InputStream is_currentLanguages;
	private static String path;
	private static MultiLanguagesFilter instanceFilter = systems.languages.MultiLanguagesFilter.getInstance();

	private static String currentLanguage ;
	private static File dir_Languages ;

	private static MultiLanguages instanceMultiLanguages  = new MultiLanguages();

	/**
	 * Private class constructor used to initialized the MultiLanguage system.
	 * It initialize the language directory path, and load the default language file according to the SystemConfiguration class.
	 */
	private MultiLanguages()
	{
	  //System.out.println("Default language : "+SystemConfiguration.getProperties().getProperty("language.default.file"));
	  //System.out.println("Directory language : "+SystemConfiguration.getProperties().getProperty("language.default.dir"));
		MultiLanguages.path = SystemConfiguration.getProperties().getProperty("language.default.dir");
		MultiLanguages.dir_Languages = new File(path);
		setLanguage(SystemConfiguration.getProperties().getProperty("language.default.file"));
	}

	/**
	 * This getter return the MultiLanguages instance.
	 * @return MultiLanguages instance.
	 */
	public static MultiLanguages getInstance()
	{
		return instanceMultiLanguages;
	}

	/**
	 * This function returns the value of a property defined by a key.
	 * This function suppress the space at the beginning and at the end of the value. 
	 * More over, if it contains $hero, then it will be replace by the hero name.
	 * @param key is the key off the property we want to get.
	 * @return null if there is no property referenced by the key, else it returns the value trim() and parsed.
	 */
	public static String getProperties(String key)
	{
		String bruteValue = multiLanguagesProperties.getProperty(key);
		try
		{
			bruteValue.length(); //We test the existance of the bruteValue;
		}catch(Exception e){
			return "null";
		}
		return bruteValue;
	}

	/**
	 * This function works exactly like getProperties(String Key), 
	 * but if there is no property referenced by the key, the the returns value will be defaultValue.
	 * @param key is the key off the property we want to get.
	 * @param defaultValue is the default value if the property is not found
	 * @return defaultValue if there is no property referenced by the key, else it returns the value trim() and parsed.
	 */
	public static String getProperties(String key, String defaultValue)
	{
		if(getProperties(key) == null)
			return defaultValue.trim();
		return getProperties(key);
	}

	/**
	 * This function returns all the name of file language (minus the extension) found into the language directory.
	 * @return if the directory does not exists, then it return null, else it will return the list of language name.
	 */
	public static LinkedList<String> getLanguagesList()
	{
		LinkedList<String> languagesList = new LinkedList<String>();
		if(!MultiLanguages.dir_Languages.exists()) /* If the directory doesn't exist */
			return null;

		for(File selectedFile : MultiLanguages.dir_Languages.listFiles( MultiLanguages.instanceFilter ))
		{
			int nomLength = selectedFile.getName().length();
			int end = nomLength - ".xml".length();
			//System.out.println("Adding : "+selectedFile.getName()); //LOG
			languagesList.add(selectedFile.getName().substring(0, end));
		}
		return languagesList;
	}

	/**
	 * This function is a setter used to change the language of the game.
	 * @param lang is the new language.
	 */
	public static void setLanguage(String lang){
	  //System.out.println("Current language is now : "+lang); //LOG
		MultiLanguages.currentLanguage = lang;
		//System.out.println("Language loading."); //LOG
		MultiLanguages.loadLanguage();
	}

	/**
	 * This function returns the current name of the file language.
	 * @return the current name of the file language.
	 */
	public String getLanguageFileName(){
		return MultiLanguages.currentLanguage;
	}
	
	 /**
   * This function returns the current name of language.
   * @return the current name of language
   */
  public String getLanguageName(){
    return MultiLanguages.currentLanguage.substring(0, (currentLanguage.length()-4));
  }

	/**
	 * This function load a language file.
	 */
	private static void loadLanguage(){
		try
		{
			if (MultiLanguages.currentLanguage.endsWith(".xml"))
				MultiLanguages.is_currentLanguages = new FileInputStream(path+MultiLanguages.currentLanguage);  	
			else
				MultiLanguages.is_currentLanguages = new FileInputStream(path+MultiLanguages.currentLanguage.concat(".xml"));  	
		}
		catch(Exception e)
		{
			System.out.println("##ERROR :Error while loadLanguage() : "
					+path+MultiLanguages.currentLanguage
					+"\n"+e.getMessage() );
			e.printStackTrace();
		}

		try {
			MultiLanguages.multiLanguagesProperties.loadFromXML(MultiLanguages.is_currentLanguages);
		} catch (InvalidPropertiesFormatException e) {
			System.out.println("##ERROR : Invalid Properties Format. Please check the following file : "
					+ MultiLanguages.is_currentLanguages
					+"\n"+ e.getMessage() );
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("##ERROR : Input/Output Exception with the following file : "
					+ MultiLanguages.is_currentLanguages
					+ e.getMessage() );
		}
	}
}
